/*
This source file is part of the open source TripleGasm project
Copyright (C) 2010 Roma Kovalev

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

For the latest info, see http://code.google.com/p/triplegasm
You can contact the author(s) via e-mail: endiannesz@gmail.com
*/

#pragma once
#ifndef BALL_HPP
#define BALL_HPP

#include <list>
#include <Ogre.h>
#include "basesphere.hpp"

namespace TripleGasm
{	
  /**A ball is a sphere that is initially not visible in the game world.
  The ball class represents a sphere that moves in a random direction, 
  at the same time it is dragged to the center of the screen, this simulates
  a gravity effect. Every frame the module of the force that pushes the sphere
  in a random direction is decreased, this simulates a difference in speed.
  .*/
  class Ball : public BaseSphere
  {
  public:
    /**Constructs a Ball.
    @params
    Pointer to a scene manager that contains a "Sphere" mesh.
    */
    Ball(Ogre::SceneManager* pSm);
    Ball();
    ~Ball();

    /**Moves the sphere.
    @params
    A variable that contains the amount of time passed since last frame. 
    */
    void Move(const Ogre::FrameEvent& evt);

    /**Attaches this sphere to a SceneNode.
    @params
    A pointer to a SceneNode, which should actually be a pointer to an
    attach point, see #mpAttachPoints.
    */
    void AttachTo(BaseSphere* pSphere);

    /**Inherits a SceneNode.
    This should be called when this sphere attaches to another sphere,
    thus it is vital that this sphere inherits the other spheres attach point.
    */
    void InheritPivot(Ogre::SceneNode* pNode);

    /**Corrects all attach points (if any are broken).
    In some cases it is not obvious how to set the attach point, this function
    iterates through all attach points and corrects them.
    */
    void CorrectSphereAttachPoints(local_matrix pSphereTable);

    /**Checks if the sphere should be removed.
    An isolated sphere is not attached to the center of the manipulator,
    it is just floating around, and should be deleted.
    @returns
    The return value is a list of all spheres that are attached to this sphere
    (including this sphere itself),
    but not attached to the center of the manipulator. */
    std::list<Ball*> IsIsolatedSphere();
    void IsIsolatedSphere(std::list<Ball*>* pSpheres);

    /**Internal function that checks if 3 spheres of the same type are linked.
    @returns
    The return value is a list of all spheres that are attached to this sphere
    (including this sphere itself) and are of the same type as this sphere.
    */
    std::list<Ball*> IsTriplePop();

  protected:
    Ogre::Vector3 mForce; /**<Which direction this sphere is moving.*/
    bool mIsAttached; /**<Is this sphere attached to the manipulator?*/
  };	
}

#endif